/* ----------------------------------------------------------------------------------------------------------------------------------------------- /

Download - 资源加载 - NEROKING.COM

< --- Public Vars ------------------------------------------------------------------------------------------------------------------------------ >

※ 提示回调函数传递 Loader 本身的常量（静态，常量）
public static const SELF:String = "Download_SELF";

※ 下载线程数（静态）
public static var thread:int = 3;

< --- Public Functions ------------------------------------------------------------------------------------------------------------------------ >

※ 加载资源（静态）
public static function load(url:String,onComplete:Function=null,onCompleteParams:Array=null,onError:Function=null,onErrorParams:Array=null,priority:Boolean=false,context:LoaderContext=null):Loader
@url:String - 下载资源的URL（绝对路径）
@onComplete:Function = null - 下载成功后执行的函数
@onCompleteParams:Array = null - 下载成功后执行函数的参数 ( 想传递Download实例本身请向数组内传入 Download.SELF )
@onError:Function = null - 下载失败时执行的函数
@onErrorParams:Array = null - 下载失败时执行函数的参数 ( 想传递Download实例本身请向数组内传入 Download.SELF )
@priority:Boolean = false - 是否优先加载
@context:LoaderContext = null - 用于定义程序域的 LoaderContext 对象

※ 中断加载（静态）
public static function kill(loader:Loader):void
@loader:Loader - 需要中断加载的 Loader

※ 添加预载（静态）
public static function addPreload(url:String,context:LoaderContext=null):void
@url:String - 预载资源的URL（绝对路径）
@context:LoaderContext = null - 用于定义程序域的 LoaderContext 对象

※ 取消预载（静态）
public static function removePreload(url:String):void
@url:String - 预载资源的URL（绝对路径）

※ 取消所有预载（静态）
public static function removeAllPreload():void

※ 返回加载百分比（静态，返回 0 - 100，只对3K以上文件有效）
public static function getPercent(loader:Loader):int
@loader:Loader - 需要返回加载百分比的 Loader

/ ----------------------------------------------------------------------------------------------------------------------------------------------- */
package com.neroking.resource{
	
	import com.neroking.resource.support.LoaderConfig;
	
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.utils.setTimeout;
	
	public class Download{
		
		// --- Vars ------------------------------------------------------------------------------------------------------------------------------- //
		
		// 提示回调函数传递 Loader 本身的常量
		public static const SELF:String = "Download_SELF";
		
		// 同时加载的线程数
		public static var thread:uint = 3;
		
		// 载入失败后重新尝试载入的次数
		private static var ReloadNum:uint = 2;
		
		// 是否正在预载
		private static var Preloading:Boolean = false;
		
		// 正在下载的序列组
		private static var LoadingList:Vector.<Loader> = new Vector.<Loader>();
		private static var LoadingConfigs:Vector.<LoaderConfig> = new Vector.<LoaderConfig>();
		
		// 等待下载的序列组
		private static var WaitingList:Vector.<Loader> = new Vector.<Loader>();
		private static var WaitingConfigs:Vector.<LoaderConfig> = new Vector.<LoaderConfig>();
		
		// 预加载的序列组
		private static var PreloadList:Vector.<Loader> = new Vector.<Loader>();
		private static var PreloadConfigs:Vector.<LoaderConfig> = new Vector.<LoaderConfig>();
		
		// 已完成加载的资源URL列表
		private static var LoadedList:Vector.<String> = new Vector.<String>();
		
		// --- Public Functions ------------------------------------------------------------------------------------------------------------------ //
		
		// 加载资源
		public static function load(url:String,onComplete:Function=null,onCompleteParams:Array=null,onError:Function=null,onErrorParams:Array=null,priority:Boolean=false,context:LoaderContext=null):Loader{
			
			// 停止预载
			StopPreload_func();
			
			// 过滤预载列表
			removePreload(url);
			
			// 建立 Loader 及 LoaderConfig
			var loader:Loader = GetResource_func(url);
			var loaderConfig:LoaderConfig = new LoaderConfig();
			loaderConfig.url = url;
			loaderConfig.onComplete = onComplete;
			loaderConfig.onCompleteParams = onCompleteParams;
			loaderConfig.onError = onError;
			loaderConfig.onErrorParams = onErrorParams;
			loaderConfig.context = context;
			loaderConfig.reloadNum = ReloadNum;
			
			// 预载处理
			if(loader.content != null){
				if(loaderConfig.onComplete != null){
					setTimeout(DelayRun_func,100,loader,loaderConfig);
				}
				return loader;
			}
			
			// 添加侦听事件
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE,LoadComplete_func);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,LoadError_func);
			
			// 序列判断
			if(LoadingList.length<thread){
				LoadingList.push(loader);
				LoadingConfigs.push(loaderConfig);
				loader.load(new URLRequest(loaderConfig.url),loaderConfig.context);
				loaderConfig.loading = true;
			}else{
				if(priority){
					WaitingList.unshift(loader);
					WaitingConfigs.unshift(loaderConfig);
				}else{
					WaitingList.push(loader);
					WaitingConfigs.push(loaderConfig);
				}
			}
			
			// 返回
			return loader;
			
		}
		
		// 中断加载
		public static function kill(loader:Loader):void{
			
			// 移除侦听
			loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,LoadComplete_func);
			loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,LoadError_func);
			
			// 移除 Loader 以及 LoaderConfig
			var index:int = LoadingList.indexOf(loader);
			if(index != -1){
				if(LoadingConfigs[index].loading){
					loader.close();
					loader.unloadAndStop();
				}
				LoadingList.splice(index,1);
				LoadingConfigs.splice(index,1);
			}else{
				index = WaitingList.indexOf(loader);
				if(index != -1){
					WaitingList.splice(index,1);
					WaitingConfigs.splice(index,1);
					loader.unloadAndStop();
				}else{
					return;
				}
			}
			
			// 调整加载序列
			if(WaitingList.length>0){
				var length:int = WaitingList.length;
				for(var i:int = 0 ; i<length ; i++){
					if(LoadingList.length<thread){
						// 向正在加载序列添加 Loader 及 LoaderConfig
						WaitingList[0].load(new URLRequest(WaitingConfigs[0].url),WaitingConfigs[0].context);
						WaitingConfigs[0].loading = true;
						LoadingList.push(WaitingList.shift());
						LoadingConfigs.push(WaitingConfigs.shift());
					}else{
						return;
					}
				}
			}else if(LoadingList.length == 0){
				// 开始预载
				StartPreload_func();
			}
			
		}
		
		// 添加预载
		public static function addPreload(url:String,context:LoaderContext=null):void{
			
			// 过滤已经下载完成的资源路径
			var length:int = LoadedList.length;
			for(var i:int = 0 ; i<length ; i++){
				if(LoadedList[i] == url){
					return;
				}
			}
			
			// 添加预载数据
			var loaderConfig:LoaderConfig = new LoaderConfig();
			loaderConfig.url = url;
			loaderConfig.context = context;
			PreloadConfigs.push(loaderConfig);
			
			// 触发预载
			if(LoadingList.length == 0 && WaitingList.length == 0){
				StartPreload_func();
			}
			
		}
		
		// 取消预载
		public static function removePreload(url:String):void{
			var length:int = PreloadConfigs.length;
			for(var i:int = 0 ; i < length ; i++){
				if(PreloadConfigs[i].url == url){
					if(Preloading && i==0){
						return;
					}else{
						PreloadConfigs.splice(i,1);
						return;
					}
				}
			}
		}
		
		// 取消所有预载
		public static function removeAllPreload():void{
			if(Preloading){
				PreloadConfigs.splice(1,PreloadConfigs.length-1);
			}else{
				PreloadConfigs.splice(0,PreloadConfigs.length);
			}
		}
		
		// 返回目标载入百分比（只对3K以上文件有效）
		public static function getPercent(loader:Loader):int{
			if(loader.contentLoaderInfo.bytesTotal>3072){
				return int(loader.contentLoaderInfo.bytesLoaded/loader.contentLoaderInfo.bytesTotal*100);	
			}else{
				return 0;	
			}
		}
		
		// --- Private Functions ----------------------------------------------------------------------------------------------------------------- //
		
		// 提取预载完成的资源
		private static function GetResource_func(url:String):Loader{
			var length:int = PreloadList.length;
			for(var i:int = 0 ; i<length ; i++){
				if(PreloadList[i].contentLoaderInfo.url == url){
					return PreloadList.splice(i,1)[0];
				}
			}			
			return new Loader();
		}
		
		// 载入完成
		private static function LoadComplete_func(evt:Event):void{
			
			var index:int = LoadingList.indexOf(LoaderInfo(evt.target).loader);
			var onComplete:Function = LoadingConfigs[index].onComplete;
			var onCompleteParams:Array = LoadingConfigs[index].onCompleteParams;
			
			// 加载成功时执行函数
			if(onComplete != null){
				if(onCompleteParams != null){
					var SelfIndex:int = onCompleteParams.indexOf(Download.SELF);
					if(SelfIndex != -1){
						onCompleteParams.splice(SelfIndex,1,LoaderInfo(evt.target).loader);
					}	
				}
				onComplete.apply(null,onCompleteParams);
			}
			
			// 提示不在载入中
			LoadingConfigs[index].loading = false;
			
			// 加入已经完成下载的资源列表
			LoadedList.push(LoaderInfo(evt.target).url);
			
			// 结束加载线程
			kill(LoaderInfo(evt.target).loader);	
			
		}
		
		// 载入失败
		private static function LoadError_func(evt:IOErrorEvent):void{
			
			
			var index:int = LoadingList.indexOf(LoaderInfo(evt.target).loader);
			var onError:Function = LoadingConfigs[index].onError;
			var onErrorParams:Array = LoadingConfigs[index].onErrorParams;

			// 重试下载
			LoadingConfigs[index].reloadNum--;
			if(LoadingConfigs[index].reloadNum>=0){
				LoaderInfo(evt.target).loader.load(new URLRequest(LoadingConfigs[index].url),LoadingConfigs[index].context);
			}else{
				// 加载失败时执行函数
				if(onError != null){
					if(onErrorParams != null){
						var SelfIndex:int = onErrorParams.indexOf(Download.SELF);
						if(SelfIndex != -1){
							onErrorParams.splice(SelfIndex,1,LoaderInfo(evt.target).loader);
						}
					}
					onError.apply(null,onErrorParams);
				}
				
				trace("warring ---> url unable load : "+LoadingConfigs[index].url);
				
				// 提示不在载入中
				LoadingConfigs[index].loading = false;
				
				// 结束加载线程
				kill(LoaderInfo(evt.target).loader);
				
				
			}
		}
		
		// 开始预载
		private static function StartPreload_func():void{
			if(PreloadConfigs.length>0){
				Preloading = true;
				var loader:Loader = new Loader();
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE,PreloadEvent_func);
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,PreloadEvent_func);
				loader.load(new URLRequest(PreloadConfigs[0].url),PreloadConfigs[0].context);
				PreloadList.push(loader);				
			}else{
				Preloading = false;
			}
		}
		
		// 停止预载
		private static function StopPreload_func():void{
			if(Preloading){
				Preloading = false;
				var length:int = PreloadList.length;
				var loader:Loader = PreloadList.splice(length-1,1)[0];
				loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,PreloadEvent_func);
				loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,PreloadEvent_func);
				loader.close();
				loader.unloadAndStop();
			}
		}
		
		// 预载侦听
		private static function PreloadEvent_func(evt:Event):void{
			var length:int = PreloadList.length;
			PreloadList[length-1].contentLoaderInfo.removeEventListener(Event.COMPLETE,PreloadEvent_func);
			PreloadList[length-1].contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,PreloadEvent_func);
			if(evt.type == Event.COMPLETE){
				LoadedList.push(PreloadList[length-1].contentLoaderInfo.url);
			}else{
				var loader:Loader = PreloadList.splice(length-1,1)[0];
				loader.unloadAndStop();
			}
			PreloadConfigs.shift();
			StartPreload_func();
		}
		
		// 延迟执行回调函数
		private static function DelayRun_func(loader:Loader,loaderConfig:LoaderConfig):void{
			
			var onComplete:Function = loaderConfig.onComplete;
			var onCompleteParams:Array = loaderConfig.onCompleteParams;
			
			if(onCompleteParams != null){
				var SelfIndex:int = onCompleteParams.indexOf(Download.SELF);
				if(SelfIndex != -1){
					onCompleteParams.splice(SelfIndex,1,loader);
				}	
			}
			onComplete.apply(null,onCompleteParams);
		}
	}
}